package dnufractal;

import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;

public class tmapblk extends tgenblk{
  public static final int clBad=2550;
  byte mean, ctr;// *exp(ctr/16)
  float fctr;
  short x0, y0, blsize;
  byte transf;
  public void msht(int amsht){
    x0*=amsht; 
    y0*=amsht;
    blsize*=amsht;
  }
  static byte inttopixbyte(int a){
    if(a<=-128)return -128;
    if(127<a)return 127;
    return (byte)a;
  }
  static int inttopix(int a){
    if(a<=0)return 0;
    if(255<=a)return 255;
    return a;
  }
  double dist(double[][] ares, int aorigx, int aorigy, int asz){
    double res=0;
    int ctBad=0;
    for(int ix=0; ix<asz; ix++)
      for(int iy=0; iy<asz; iy++){
        if(cmpr.morigdata[aorigx+ix][aorigy+iy]==clBad){ctBad++;}
        else{
          double d=cmpr.morigdata[aorigx+ix][aorigy+iy]-(fctr*ares[ix][iy]+mean);
          res+=Math.abs(d); 
        }
      }
//    int ctAll = asz*asz;
//    if(ctAll==ctBad)res=ctAll*255;
//    else res*=ctAll/(ctAll-ctBad);
    
    return res;
  }
  public boolean map(int aresx, int aresy, int aressz, double adelta){
    System.out.println(aresx+" "+ aresy+" "+ aressz+" "+ adelta);

    int origsz=cmpr.datasz;
    double sumres=cmpr.sum(aresx, aresy, aressz);
    double rr=sumres/(aressz*aressz);
    for(int blksz=origsz; aressz<blksz; blksz/=2){
      for(int ix=0; ix<=origsz-blksz; ix++)
        for(int iy=0; iy<=origsz-blksz; iy++)
          for(byte ir=0; ir<4; ir++)
            for(int im=0; im<2; im++){
              cmpr.msht(ix, iy, blksz, aressz, ir, im!=0);//область кандидат
              //подсчитаем среднее на этой области(точнее суммарную яркость)
              double summshtdata=0;
              for(int jx=0;jx<aressz;jx++)
                for(int jy=0;jy<aressz;jy++)
                  summshtdata+=cmpr.mshtdata[jx][jy];
    //          meanint/=(aressz*aressz);
              double dd=summshtdata/(aressz*aressz);
              //подсчитали
              double alpha=0, beta=0;
              for(int jx=0;jx<aressz;jx++)
                for(int jy=0;jy<aressz;jy++){
                  double d=cmpr.mshtdata[jx][jy];
                  alpha+=(d-dd)*(cmpr.morigdata[aresx+jx][aresy+jy]-rr);
                  beta+=(d-dd)*(d-dd);
                }
              fctr=(float)(alpha/beta);
              mean=inttopixbyte((int)(rr-fctr*dd));
              //...
              if(dist(cmpr.mshtdata, aresx, aresy, aressz) <= adelta){
                //..
                x0=(short)ix; y0=(short)iy;blsize=(short)blksz;
                transf=ir;
                if(im!=0)transf+=4;
                System.out.println("x0="+x0+" y0="+y0+" blsize="+blsize+" mean="+mean+" ir="+ir+" im="+im);
                return true;
              }
            }
    }
    return false;
  }
  public void ucmp(int aresx, int aresy, int aressz){
    byte rotation=transf;
    System.out.println(aresx + "  "+aresy +"  "+ aressz);

    if(transf>3)rotation-=4;
    cmpr.msht(x0, y0, blsize, aressz, rotation, transf>3);//область кандидат
    //..
    for(int jx=0;jx<aressz;jx++)
      for(int jy=0;jy<aressz;jy++)
        cmpr.mresdata[aresx+jx][aresy+jy]=inttopix((int)(fctr*cmpr.mshtdata[jx][jy]+mean));
  }
  public void save(){
    cmpr.wbit(false);
    try {
      cmpr.dos.writeByte(mean);
      cmpr.dos.writeFloat(fctr);
      cmpr.dos.writeShort(x0);
      cmpr.dos.writeShort(y0);
      cmpr.dos.writeShort(blsize);
    } catch (IOException ex) {
      Logger.getLogger(tmapblk.class.getName()).log(Level.SEVERE, null, ex);
    }
  }
  public void load(){
    try {
      mean=cmpr.dis.readByte();
      fctr=cmpr.dis.readFloat();
      x0=cmpr.dis.readShort();
      y0=cmpr.dis.readShort();
      blsize=cmpr.dis.readShort();
    } catch (IOException ex) {
      Logger.getLogger(tmapblk.class.getName()).log(Level.SEVERE, null, ex);
    }
  }
}
